home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 2001 May
/
SGI Freeware 2001 May - Disc 3.iso
/
dist
/
fw_elisp-intro.idb
/
usr
/
freeware
/
info
/
emacs-lisp-intro.info-6.z
/
emacs-lisp-intro.info-6
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
Macintosh to JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
GNU Info File
|
1998-10-28
|
48.5 KB
|
1,192 lines
This is Info file emacs-lisp-intro.info, produced by Makeinfo version
1.67 from the input file emacs-lisp-intro.texi.
This is an introduction to `Programming in Emacs Lisp', for people
who are not programmers.
Edition 1.05, 21 October 1997
Copyright (C) 1990, '91, '92, '93, '94, '95, '97 Free Software
Foundation, Inc.
Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.
Permission is granted to copy and distribute modified versions of
this manual under the conditions for verbatim copying, provided also
that the sections entitled "Copying" and "GNU General Public License"
are included exactly as in the original, and provided that the entire
resulting derived work is distributed under the terms of a permission
notice identical to this one.
Permission is granted to copy and distribute translations of this
manual into another language, under the above conditions for modified
versions, except that this permission notice may be stated in a
translation approved by the Free Software Foundation.
File: emacs-lisp-intro.info, Node: progn, Next: Summing up zap-to-char, Prev: search-forward, Up: zap-to-char
The `progn' Function
--------------------
`progn' is a function that causes each of its arguments to be
evaluated in sequence and then returns the value of the last one. The
preceding expressions are evaluated only for the side effects they
perform. The values produced by them are discarded.
The template for a `progn' expression is very simple:
(progn
BODY...)
In `zap-to-char', the `progn' expression has to do two things: put
point in exactly the right position; and return the location of point
so that `kill-region' will know how far to kill to.
The first argument to the `progn' is `search-forward'. When
`search-forward' finds the string, the function leaves point
immediately after the last character in the target string. (In this
case the target string is just one character long.) If the search is
backwards, `search-forward' leaves point just before the first
character in the target. The movement of point is a side effect.
The second and last argument to `progn' is the expression `(point)'.
This expression returns the value of point, which in this case will be
the location to which it has been moved by `search-forward'. This
value is returned by the `progn' expression and is passed to
`kill-region' as `kill-region''s second argument.
File: emacs-lisp-intro.info, Node: Summing up zap-to-char, Next: v-18-zap-to-char, Prev: progn, Up: zap-to-char
Summing up `zap-to-char'
------------------------
Now that we have seen how `search-forward' and `progn' work, we can
see how the `zap-to-char' function works as a whole.
The first argument to `kill-region' is the position of the cursor
when the `zap-to-char' command is given--the value of point at that
time. Within the `progn', the search function then moves point to just
after the zapped-to-character and `point' returns the value of this
location. The `kill-region' function puts together these two values of
point, the first one as the beginning of the region and the second one
as the end of the region, and removes the region.
The `progn' function is necessary because the `kill-region' command
takes two arguments; and it would fail if `search-forward' and `point'
expressions were written in sequence as two additional arguments. The
`progn' expression is a single argument to `kill-region' and returns
the one value that `kill-region' needs for its second argument.
File: emacs-lisp-intro.info, Node: v-18-zap-to-char, Prev: Summing up zap-to-char, Up: zap-to-char
The Version 18 Implementation
-----------------------------
The version 18 implementation of `zap-to-char' is slightly different
from the version 19 implementation: it zaps the text up to but not
including the zapped-to-character; and zaps to the end of the buffer if
the specified character is not found.
The difference is in the second argument to the `kill-region'
command. Where the version 19 implementation looks like this:
(progn
(search-forward (char-to-string char) nil nil arg)
(point))
The version 18 implementation looks like this:
(if (search-forward (char-to-string char) nil t arg)
(progn (goto-char
(if (> arg 0) (1- (point)) (1+ (point))))
(point))
(if (> arg 0)
(point-max)
(point-min)))
This looks considerably more complicated, but the code can be readily
understood if it is looked at part by part.
The first part is:
(if (search-forward (char-to-string char) nil t arg)
This fits into an `if' expression that does the following job, as we
shall see:
(if ABLE-TO-LOCATE-ZAPPED-FOR-CHARACTER-AND-MOVE-POINT-TO-IT
THEN-MOVE-POINT-TO-THE-EXACT-SPOT-AND-RETURN-THIS-LOCATION
ELSE-MOVE-TO-END-OF-BUFFER-AND-RETURN-THAT-LOCATION)
Evaluation of the `if' expression specifies the second argument to
`kill-region'. Since the first argument is point, this process makes
it possible for `kill-region' to remove the text between point and the
zapped-to location.
We have already described how `search-forward' moves point as a side
effect. The value that `search-forward' returns is `t' if the search
is successful and either `nil' or an error message depending on the
value of the third argument to `search-forward'. In this case, `t' is
the third argument and it causes the function to return `nil' when the
search fails. As we will see, it is easy to write the code for
handling the case when the search returns `nil'.
In the version 18 implementation of `zap-to-char', the search takes
place because the `if' causes the search expression to be evaluated as
its true-or-false-test. If the search is successful, Emacs evaluates
the then-part of the `if' expression. On the other hand, if the search
fails, Emacs evaluates the else-part of the `if' expression.
In the `if' expression, when the search succeeds, a `progn'
expression is executed--which is to say, it is run as a program.
As we said earlier, `progn' is a function that causes each of its
arguments to be evaluated in sequence and then returns the value of the
last one. The preceding expressions are evaluated only for the side
effects they perform. The values produced by them are discarded.
In this version of `zap-to-char', the `progn' expression is executed
when the `search-forward' function finds the character for which it is
searching. The `progn' expression has to do two things: put point in
exactly the right position; and return the location of point so that
`kill-region' will know how far to kill to.
The reason for all the code in the `progn' is that when
`search-forward' finds the string it is looking for, it leaves point
immediately after the last character in the target string. (In this
case the target string is just one character long.) If the search is
backwards, `search-forward' leaves point just before the first
character in the target.
However, this version of the `zap-to-char' function is designed so
that it does not remove the character being zapped to. For example, if
`zap-to-char' is to remove all the text up to a `z', this version will
not remove the `z' as well. So point has to be moved just enough that
the zapped-to character is not removed.
* Menu:
* progn body:: The body of the `progn' expression
File: emacs-lisp-intro.info, Node: progn body, Prev: v-18-zap-to-char, Up: v-18-zap-to-char
The body of the `progn' expression
..................................
The body of the `progn' consists of two expressions. Spread out to
delineate the different parts more clearly, and with comments added, the
`progn' expression looks like this:
(progn
(goto-char ; First expression in `progn'.
(if (> arg 0) ; If `arg' is positive,
(1- (point)) ; move back one character;
(1+ (point)))) ; else move forward one character.
(point)) ; Second expression in `progn':
; return position of point.
The `progn' expression does this: when the search is forward (`arg' is
positive), Emacs leaves point just after the searched-for character.
By moving point back one position, the character is uncovered. In this
case, the expression in the `progn' reads as follows: `(goto-char (1-
(point)))'. This moves point one character back. (The `1-' function
subtracts one from its argument, just as `1+' adds ones to its
argument.) On the other hand, if the argument to `zap-to-character' is
negative, the search will be backwards. The `if' detects this and the
expression reads: `(goto-char (1+ (point)))'. (The `1+' function adds
one to its argument.)
The second and last argument to `progn' is the expression `(point)'.
This expression returns the value of the position to which point is
moved by the first argument to `progn'. This value is then returned by
the `if' expression of which it is a part and is passed to
`kill-region' as `kill-region''s second argument.
In brief, the function works like this: the first argument to
`kill-region' is the position of the cursor when the `zap-to-char'
command is given--the value of point at that time. The search function
then moves point if the search is successful. The `progn' expression
moves point just enough so the zapped to character is not removed, and
returns the value of point after all this is done. The `kill-region'
function then removes the region.
Finally, the else-part of the `if' expression takes care of the
situation in which the zapped-towards character is not found. If the
argument to the `zap-to-char' function is positive (or if none is
given) and the zapped-to character is not found, all the text is
removed from the current position of point to the end of the accessible
region of the buffer (the end of the buffer if there is no narrowing).
If the `arg' is negative and the zapped-to character is not found, the
operation goes to the beginning of the accessible region. The code for
this is a simple `if' clause:
(if (> arg 0) (point-max) (point-min))
This says that if `arg' is a positive number, return the value of
`point-max', otherwise, return the value of `point-min'.
For review, here is the code involving `kill-region', with comments:
(kill-region
(point) ; beginning-of-region
(if (search-forward
(char-to-string char) ; target
nil ; limit-of-search: none
t ; Return `nil' if fail.
arg) ; repeat-count.
(progn ; then-part
(goto-char
(if (> arg 0)
(1- (point))
(1+ (point))))
(point))
(if (> arg 0) ; else-part
(point-max)
(point-min))))
As you can see, the version 19 implementation does slightly less
than the version 18 implementation, but is much simpler.
File: emacs-lisp-intro.info, Node: kill-region, Next: delete-region, Prev: zap-to-char, Up: Cutting & Storing Text
`kill-region'
=============
The `zap-to-char' function uses the `kill-region' function. This
function is very simple; leaving out part of its documentation string,
it looks like this:
(defun kill-region (beg end)
"Kill between point and mark.
The text is deleted but saved in the kill ring."
(interactive "*r")
(copy-region-as-kill beg end)
(delete-region beg end))
The main point to note is that it uses the `delete-region' and
`copy-region-as-kill' functions which are described in following
sections.
File: emacs-lisp-intro.info, Node: delete-region, Next: defvar, Prev: kill-region, Up: Cutting & Storing Text
`delete-region': A Digression into C
====================================
The `zap-to-char' command uses the `kill-region' function, which in
turn uses two other functions, `copy-region-as-kill' and
`delete-region'. The `copy-region-as-kill' function will be described
in a following section; it puts a copy of the region in the kill ring
so it can be yanked back. (*Note `copy-region-as-kill':
copy-region-as-kill.)
The `delete-region' function removes the contents of a region and
you cannot get it back.
Unlike the other code discussed here, `delete-region' is not written
in Emacs Lisp; it is written in C and is one of the primitives of the
GNU Emacs system. Since it is very simple, I will digress briefly from
Lisp and describe it here.
Like many of the other Emacs primitives, `delete-region' is written
as an instance of a C macro, a macro being a template for code. The
first section of the macro looks like this:
DEFUN ("delete-region", Fdelete_region, Sdelete_region, 2, 2, "r",
"Delete the text between point and mark.\n\
When called from a program, expects two arguments,\n\
character numbers specifying the stretch to be deleted.")
Without getting into the details of the macro writing process, let me
point out that this macro starts with the word `DEFUN'. The word
`DEFUN' was chosen since the code serves the same purpose as `defun'
does in Lisp. The word `DEFUN' is followed by seven parts inside of
parentheses:
* The first part is the name given to the function in Lisp, in this
case, `delete-region'.
* The second part is the name of the function in C, `Fdelete_region'.
By convention, it starts with `F'. Since C does not use hyphens
in names, an underscore is used instead.
* The third part is the name for the C constant structure that
records information on this function for internal use. It is the
name of the function in C but begins with an `S' instead of an `F'.
* The fourth and fifth parts specify the minimum and maximum number
of arguments the function can have. In this case, the function
demands exactly 2 arguments.
* The sixth part is just like the argument that follows the
`interactive' declaration in a function written in Lisp: a letter
followed, perhaps, by a prompt. In this case, the letter is `"r"'
which indicates that the two arguments to the function will be the
position of the beginning and end of a region in the buffer. In
this code, there isn't any prompt.
* The seventh part is a documentation string, just like the one for a
function written in Emacs Lisp, except that every newline must be
written explicitly as `\n' followed by a backslash and carriage
return.
The formal parameters come next, with a statement of what kind of
object they are, and then what might be called the `body' of the macro.
For `delete-region' the `body' consists of the following three lines:
validate_region (&b, &e);
del_range (XINT (b), XINT (e));
return Qnil;
The first function, `validate_region' checks whether the values
passed as the beginning and end of the region are the proper type and
are within range. The second function, `del_range', actually deletes
the text. If the function completes its work without error, the third
line returns `Qnil' to indicate this.
`del_range' is a complex function we will not look into. It updates
the buffer and does other things. However, it is worth looking at the
two arguments passed to `del_range'. These are `XINT (b)' and
`XINT (e)'. As far as the C language is concerned, `b' and `e' are two
thirty-two bit integers that mark the beginning and end of the region
to be deleted. But like other numbers in Emacs Lisp, only twenty-four
bits of the thirty-two bits are used for the number; the remaining
eight bits are used for keeping track of the type of information and
other purposes. (On certain machines, only six bits are so used.) In
this case, the eight bits are used to indicate that these numbers are
for buffer positions. When bits of a number are used this way, they
are called a "tag". The use of the eight bit tag on each thirty-two
bit integer made it possible to write Emacs to run much faster than it
would otherwise. On the other hand, with numbers limited to
twenty-four bits, Emacs buffers are limited to approximately eight
megabytes. (You can sharply increase the maximum buffer size by adding
defines for `VALBITS' and `GCTYPEBITS' in the `emacs/src/config.h' file
before compiling. See the note in the `emacs/etc/FAQ' file that is
part of the Emacs distribution.)
`XINT' is a C macro that extracts the 24 bit number from the
thirty-two bit Lisp object; the eight bits used for other purposes are
discarded. So `del_range (XINT (b), XINT (e))' deletes the region
between the beginning position, `b', and the ending position, `e'.
From the point of view of the person writing Lisp, Emacs is all very
simple; but hidden underneath is a great deal of complexity to make it
all work.
File: emacs-lisp-intro.info, Node: defvar, Next: copy-region-as-kill, Prev: delete-region, Up: Cutting & Storing Text
Initializing a Variable with `defvar'
=====================================
Unlike the `delete-region' function, the `copy-region-as-kill'
function is written in Emacs Lisp. It copies a region in a buffer and
saves it in a variable called the `kill-ring'. This section describes
how this variable is created and initialized.
(Again we note that the term `kill-ring' is a misnomer. The text
that is clipped out of the buffer can be brought back; it is not a ring
of corpses, but a ring of resurrectable text.)
In Emacs Lisp, a variable such as the `kill-ring' is created and
given an initial value by using the `defvar' special form. The name
comes from "define variable".
The `defvar' special form is similar to `setq' in that it sets the
value of a variable. It is unlike `setq' in two ways: first, it only
sets the value of the variable if the variable does not already have a
value. If the variable already has a value, `defvar' does not override
the existing value. Second, `defvar' has a documentation string.
You can see the current value of a variable, any variable, by using
the `describe-variable' function, which is usually invoked by typing
`C-h v'. If you type `C-h v' and then `kill-ring' (followed by <RET>)
when prompted, you will see what is in your current kill ring--this may
be quite a lot! Conversely, if you have been doing nothing this Emacs
session except read this document, you may have nothing in it. At the
end of the `*Help*' buffer, you will see the documentation for
`kill-ring':
Documentation:
List of killed text sequences.
The kill ring is defined by a `defvar' in the following way:
(defvar kill-ring nil
"List of killed text sequences.")
In this variable definition, the variable is given an initial value of
`nil', which makes sense, since if you have saved nothing, you want
nothing back if you give a `yank' command. The documentation string is
written just like the documentation string of a `defun'. As with the
documentation string of the `defun', the first line of the
documentation should be a complete sentence, since some commands, like
`apropos', print only the first line of documentation. Succeeding
lines should not be indented; otherwise they look odd when you use `C-h
v' (`describe-variable').
Most variables are internal to Emacs, but some are intended as
options that you can readily set with the `edit-options' command.
(These settings last only for the duration of an editing session; to
set a value permanently, write a `.emacs' file. *Note Your `.emacs'
File: Emacs Initialization.)
A readily settable variable is distinguished from others in Emacs by
an asterisk, `*', in the first column of its documentation string.
For example:
(defvar line-number-mode nil
"*Non-nil means display line number in mode line.")
This means that you can use the `edit-options' command to change the
value of `line-number-mode'.
Of course, you can also change the value of `line-number-mode' by
evaluating it within a `setq' expression, like this:
(setq line-number-mode t)
*Note Using `setq': Using setq.
File: emacs-lisp-intro.info, Node: copy-region-as-kill, Next: cons & search-fwd Review, Prev: defvar, Up: Cutting & Storing Text
`copy-region-as-kill'
=====================
The `copy-region-as-kill' function copies a region of text from a
buffer and saves it in a variable called the `kill-ring'.
If you call `copy-region-as-kill' immediately after a `kill-region'
command, Emacs appends the newly copied text to the previously copied
text. This means that if you yank back the text, you get it all, from
both this and the previous operation. On the other hand, if some other
command precedes the `copy-region-as-kill', the function copies the
text into a separate entry in the kill ring.
Here is the complete text of the version 18 `copy-region-as-kill',
formatted for clarity with several comments added:
(defun copy-region-as-kill (beg end)
"Save the region as if killed, but don't kill it."
(interactive "r")
(if (eq last-command 'kill-region)
;; then-part: Combine newly copied text
;; with previously copied text.
(kill-append (buffer-substring beg end) (< end beg))
;; else-part: Add newly copied text as a new element
;; to the kill ring and shorten the kill ring if necessary.
(setq kill-ring
(cons (buffer-substring beg end) kill-ring))
(if (> (length kill-ring) kill-ring-max)
(setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
(setq this-command 'kill-region)
(setq kill-ring-yank-pointer kill-ring))
As usual, this function can be divided into its component parts:
(defun copy-region-as-kill (ARGUMENT-LIST)
"DOCUMENTATION..."
(interactive "r")
BODY...)
The arguments are `beg' and `end' and the function is interactive
with `"r"', so the two arguments must refer to the beginning and end of
the region. If you have been reading though this document from the
beginning, understanding these parts of a function is almost becoming
routine.
The documentation is somewhat confusing unless you remember that the
word `kill' has a meaning different from its usual meaning.
The body of the function starts with an `if' clause. What this
clause does is distinguish between two different situations: whether or
not this command is executed immediately after a previous `kill-region'
command. In the first case, the new region is appended to the
previously copied text. Otherwise, it is inserted into the beginning
of the kill ring as a separate piece of text from the previous piece.
The last two lines of the function are two `setq' expressions. One
of them sets the variable `this-command' to `kill-region' and the other
sets the variable `kill-ring-yank-pointer' to point to the kill ring.
The body of `copy-region-as-kill' merits discussion in detail.
* Menu:
* copy-region-as-kill body:: The body of `copy-region-as-kill'
File: emacs-lisp-intro.info, Node: copy-region-as-kill body, Prev: copy-region-as-kill, Up: copy-region-as-kill
The Body of `copy-region-as-kill'
---------------------------------
The `copy-region-as-kill' function is written so that two or more
kills in a row combine their text into a single entry. If you yank back
the text from the kill ring, you get it all in one piece. Moreover,
kills that kill forward from the current position of the cursor are
added to the end of the previously copied text and commands that copy
text backwards add it to the beginning of the previously copied text.
This way, the words in the text stay in the proper order.
The function makes use of two variables that keep track of the
current and previous Emacs command. The two variables are
`this-command' and `last-command'.
Normally, whenever a function is executed, Emacs sets the value of
`this-command' to the function being executed (which in this case would
be `copy-region-as-kill'). At the same time, Emacs sets the value of
`last-command' to the previous value of `this-command'. However, the
`copy-region-as-kill' command is different; it sets the value of
`this-command' to `kill-region', which is the name of the function that
calls `copy-region-as-kill'.
In the first part of the body of the `copy-region-as-kill' function,
an `if' expression determines whether the value of `last-command' is
`kill-region'. If so, the then-part of the `if' expression is
evaluated; it uses the `kill-append' function to concatenate the text
copied at this call to the function with the text already in the first
element (the CAR) of the kill ring. On the other hand, if the value of
`last-command' is not `kill-region', then the `copy-region-as-kill'
function attaches a new element to the kill ring.
The `if' expression reads as follows; it uses `eq', which is a
function we have not yet seen:
(if (eq last-command 'kill-region)
;; then-part
(kill-append (buffer-substring beg end) (< end beg))
The `eq' function tests whether its first argument is the same Lisp
object as its second argument. The `eq' function is similar to the
`equal' function in that it is used to test for equality, but differs
in that it determines whether two representations are actually the same
object inside the computer, but with different names. `equal'
determines whether the structure and contents of two expressions are
the same.
* Menu:
* kill-append function:: The `kill-append' function
* copy-region-as-kill else-part:: The else-part of `copy-region-as-kill'
File: emacs-lisp-intro.info, Node: kill-append function, Next: copy-region-as-kill else-part, Prev: copy-region-as-kill body, Up: copy-region-as-kill body
The `kill-append' function
..........................
The `kill-append' function looks like this:
(defun kill-append (string before-p)
(setcar kill-ring
(if before-p
(concat string (car kill-ring))
(concat (car kill-ring) string))))
We can look at this function in parts. The `setcar' function uses
`concat' to concatenate the new text to the CAR of the kill ring.
Whether it prepends or appends the text depends on the results of an
`if' expression:
(if before-p ; if-part
(concat string (car kill-ring)) ; then-part
(concat (car kill-ring) string)) ; else-part
If the region being killed is before the region that was killed in the
last command, then it should be prepended before the material that was
saved in the previous kill; and conversely, if the killed text follows
what was just killed, it should be appended after the previous text.
The `if' expression depends on the predicate `before-p' to decide
whether the newly saved text should be put before or after the
previously saved text.
The symbol `before-p' is the name of one of the arguments to
`kill-append'. When the `kill-append' function is evaluated, it is
bound to the value returned by evaluating the actual argument. In this
case, this is the expression `(< end beg)'. This expression does not
directly determine whether the killed text in this command is located
before or after the kill text of the last command; what is does is
determine whether the value of the variable `end' is less than the
value of the variable `beg'. If it is, it means that the user is most
likely heading towards the beginning of the buffer. Also, the result
of evaluating the predicate expression, `(< end beg)', will be true and
the text will be prepended before the previous text. On the other
hand, if the value of the variable `end' is greater than the value of
the variable `beg', the text will be appended after the previous text.
When the newly saved text will be prepended, then the string with
the new text will be concatenated before the old test:
(concat string (car kill-ring))
But if the text will be appended, it will be concatenated after the old
text:
(concat (car kill-ring) string))
To understand how this works, we first need to review the `concat'
function. The `concat' function links together or unites two strings
of text. The result is a string. For example:
(concat "abc" "def")
=> "abcdef"
(concat "new "
(car '("first element" "second element")))
=> "new first element"
(concat (car
'("first element" "second element")) " modified")
=> "first element modified"
We can now make sense of `kill-append': it modifies the contents of
the kill ring. The kill ring is a list, each element of which is saved
text. The `setcar' function actually changes the first element of this
list. It does this by using `concat' to replace the old first element
of the kill ring (the CAR of the kill ring) with a new first element
made by concatenating together the old saved text and the newly saved
text. The newly saved text is put in front of the old text or after
the old text, depending on whether it is in front of or after the old
text in the buffer from which it is cut. The whole concatenation
becomes the new first element of the kill ring.
Incidentally, this is what the beginning of my current kill ring
looks like:
("concatenating together" "saved text" "element" ...
File: emacs-lisp-intro.info, Node: copy-region-as-kill else-part, Prev: kill-append function, Up: copy-region-as-kill body
The else-part of `copy-region-as-kill'
......................................
Now, back to the explanation of `copy-region-as-kill':
If the last command is not `kill-region', then instead of calling
`kill-append', it calls the else-part of the following code:
(if TRUE-OR-FALSE-TEST
WHAT-IS-DONE-IF-TEST-RETURNS-TRUE
;; else-part
(setq kill-ring
(cons (buffer-substring beg end) kill-ring))
(if (> (length kill-ring) kill-ring-max)
(setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
The `setq' line of the else-part sets the new value of the kill ring
to what results from adding the string being killed to the old kill
ring.
We can see how this works with a little example:
(setq example-list '("here is a clause" "another clause"))
After evaluating this expression with `C-x C-e', you can evaluate
`example-list' and see what it returns:
example-list
=> ("here is a clause" "another clause")
Now, we can add a new element on to this list by evaluating the
following expression:
(setq example-list (cons "a third clause" example-list))
When we evaluate `example-list', we find its value is:
example-list
=> ("a third clause" "here is a clause" "another clause")
Thus, the third clause was added to the list by `cons'.
This is exactly similar to what the `setq' and `cons' do in the
function, except that `buffer-substring' is used to pull out a copy of
a region of text and hand it to the `cons'. Here is the line again:
(setq kill-ring (cons (buffer-substring beg end) kill-ring))
The next segment of the else-part of `copy-region-as-kill' is
another `if' clause. This `if' clause keeps the kill ring from growing
too long. It reads as follows:
(if (> (length kill-ring) kill-ring-max)
(setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))
This code checks whether the length of the kill ring is greater than
the maximum permitted length. This is the value of `kill-ring-max'
(which is 30, by default). If the length of the kill ring is too long,
then this code sets the last element of the kill ring to `nil'. It
does this by using two functions, `nthcdr' and `setcdr'.
We looked at `setcdr' earlier (*note `setcdr': setcdr.). It sets
the CDR of a list, just as `setcar' sets the CAR of a list. In this
case, however, `setcdr' will not be setting the `cdr' of the whole kill
ring; the `nthcdr' function is used to cause it to set the `cdr' of the
next to last element of the kill ring--this means that since the `cdr'
of the next to last element is the last element of the kill ring, it
will set the last element of the kill ring.
The `nthcdr' function works by repeatedly taking the CDR of a
list--it takes the CDR of the CDR of the CDR ... It does this N times
and returns the results.
Thus, if we had a four element list that was supposed to be three
elements long, we could set the CDR of the next to last element to
`nil', and thereby shorten the list.
You can see this by evaluating the following three expressions in
turn. First set the value of `trees' to `(maple oak pine birch)', then
set the CDR of its second CDR to `nil' and then find the value of
`trees':
(setq trees '(maple oak pine birch))
=> (maple oak pine birch)
(setcdr (nthcdr 2 trees) nil)
=> nil
trees
=> (maple oak pine)
(The value returned by the `setcdr' expression is `nil' since that is
what the CDR is set to.)
To repeat, in `copy-region-as-kill', the `nthcdr' function takes the
CDR a number of times that is one less than the maximum permitted size
of the kill ring and sets the CDR of that element (which will be the
rest of the elements in the kill ring) to `nil'. This prevents the
kill ring from growing too long.
The next to last line of the `copy-region-as-kill' function is
`(setq this-command 'kill-region)'
This line is not part of either the inner or the outer `if' expression,
so it is evaluated every time `copy-region-as-kill' is called. Here we
find the place where `this-command' is set to `kill-region'. As we saw
earlier, when the next command is given, the variable `last-command'
will be given this value.
Finally, the last line of the `copy-region-as-kill' function is:
(setq kill-ring-yank-pointer kill-ring)
The `kill-ring-yank-pointer' is a global variable that is set to be
the `kill-ring'.
Even though the `kill-ring-yank-pointer' is called a `pointer', it
is a variable just like the kill ring. However, the name has been
chosen to help humans understand how the variable is used. The
variable is used in functions such as `yank' and `yank-pop' (*note
Yanking Text Back: Yanking.).
This leads us to the code for bringing back text that has been cut
out of the buffer--the yank commands. However, before discussing the
yank commands, it is better to learn how lists are implemented in a
computer. This will make clear such mysteries as the use of the term
`pointer'.
File: emacs-lisp-intro.info, Node: cons & search-fwd Review, Next: search Exercises, Prev: copy-region-as-kill, Up: Cutting & Storing Text
Review
======
Here is a brief summary of some recently introduced functions.
`car'
`cdr'
`car' returns the first element of a list; `cdr' returns the
second and subsequent elements of a list.
For example:
(car '(1 2 3 4 5 6 7))
=> 1
(cdr '(1 2 3 4 5 6 7))
=> (2 3 4 5 6 7)
`cons'
`cons' constructs a list by prepending its first argument to its
second argument.
For example:
(cons 1 '(2 3 4))
=> (1 2 3 4)
`nthcdr'
Return the result of taking `cdr' `n' times on a list. The `rest
of the rest' as it were.
For example:
(nthcdr 3 '(1 2 3 4 5 6 7))
=> (4 5 6 7)
`setcar'
`setcdr'
`setcar' changes the first element of a list; `setcdr' changes the
second and subsequent elements of a list.
For example:
(setq triple '(1 2 3))
(setcar triple '37)
triple
=> (37 2 3)
(setcdr triple '("foo" "bar"))
triple
=> (37 "foo" "bar")
`progn'
Evaluate each argument in sequence and then return the value of the
last.
For example:
(progn 1 2 3 4)
=> 4
`save-restriction'
Record whatever narrowing is in effect in the current buffer, if
any, and restore that narrowing after evaluating the arguments.
`search-forward'
Search for a string, and if the string is found, move point.
Takes four arguments:
1. The string to search for.
2. Optionally, the limit of the search.
3. Optionally, what to do if the search fails, return `nil' or an
error message.
4. Optionally, how many times to repeat the search; if negative,
the search goes backwards.
`kill-region'
`delete-region'
`copy-region-as-kill'
`kill-region' cuts the text between point and mark from the buffer
and stores that text in the kill ring, so you can get it back by
yanking.
`delete-region' removes the text between point and mark from the
buffer and throws it away. You cannot get it back.
`copy-region-as-kill' copies the text between point and mark into
the kill ring, from which you can get it by yanking. The function
does not cut or remove the text from the buffer.
File: emacs-lisp-intro.info, Node: search Exercises, Prev: cons & search-fwd Review, Up: Cutting & Storing Text
Searching Exercises
===================
* Write an interactive function that searches for a string. If the
search finds the string, leave point after it and display a message
that says "Found!". (Do not use `search-forward' for the name of
this function; if you do, you will overwrite the existing version
of `search-forward' that comes with Emacs. Use a name such as
`test-search' instead.)
* Write a function that prints the third element of the kill ring in
the echo area, if any; if the kill ring does not contain a third
element, print an appropriate message.
* As of version 19.29, `copy-region-as-kill' no longer sets
`this-command'. What are the consequences of this change? What
do you suppose motivated it?
File: emacs-lisp-intro.info, Node: List Implementation, Next: Yanking, Prev: Cutting & Storing Text, Up: Top
How Lists are Implemented
*************************
In Lisp, atoms are recorded in a straightforward fashion; if the
implementation is not straightforward in practice, it is, nonetheless,
straightforward in theory. The atom `rose', for example, is recorded
as the four contiguous letters `r', `o', `s', `e'. A list, on the
other hand, is kept differently. The mechanism is equally simple, but
it takes a moment to get used to the idea. A list is kept using a
series of pairs of pointers. In the series, the first pointer in each
pair points to an atom or to another list, and the second pointer in
each pair points to the next pair, or to the symbol `nil', which marks
the end of the list.
A pointer itself is quite simply the electronic address of what is
pointed to. Hence, a list is kept as a series of electronic addresses.
For example, the list `(rose violet buttercup)' has three elements,
`rose', `violet', and `buttercup'. In the computer, the electronic
address of `rose' is recorded in a segment of computer memory along
with the address that gives the electronic address of where the atom
`violet' is located; and that address (the one that tells where
`violet' is located) is kept along with an address that tells where the
address for the atom `buttercup' is located.
This sounds more complicated than it is and is easier seen in a
diagram:
___ ___ ___ ___ ___ ___
|___|___|--> |___|___|--> |___|___|--> nil
| | |
| | |
--> rose --> violet --> buttercup
In the diagram, each box represents a word of computer memory that
holds a Lisp object, usually in the form of a memory address. The
boxes, i.e. the addresses, are in pairs. Each arrow points to what the
address is the address of, either an atom or another pair of addresses.
The first box is the electronic address of `rose' and the arrow points
to `rose'; the second box is the address of the next pair of boxes, the
first part of which is the address of `violet' and the second part of
which is the address of the next pair. The very last box points to the
symbol `nil', which marks the end of the list.
When a variable is set to a list with a function such as `setq', it
stores the address of the first box in the variable. Thus, evaluation
of the expression
(setq bouquet '(rose violet buttercup))
creates a situation like this:
bouquet
|
| ___ ___ ___ ___ ___ ___
--> |___|___|--> |___|___|--> |___|___|--> nil
| | |
| | |
--> rose --> violet --> buttercup
In this case, the symbol `bouquet' holds the address of the first pair
of boxes. Indeed, the symbol `bouquet' consists of a group of
address-boxes, one of which is the address of the printed word
`bouquet', a second of which is the address of a function definition
attached to the symbol, if any, a third of which is the address of the
first pair of address-boxes for the list `(rose violet buttercup)', and
so on.
This same list can be illustrated in a different sort of box notation
like this:
bouquet
|
| -------------- --------------- ----------------
| | car | cdr | | car | cdr | | car | cdr |
-->| rose | o------->| violet | o------->| butter- | nil |
| | | | | | | cup | |
-------------- --------------- ----------------
In an earlier section, I suggested that you might imagine a symbol as
being a chest of drawers. The function definition is put in one drawer,
the value in another, and so on. What is put in the drawer holding the
value can be changed without affecting the contents of the drawer
holding the function definition, and vice-versa. Actually, what is put
in each drawer is the address of the value or function definition. It
is as if you found an old chest in the attic, and in one of its drawers
you found a map giving you directions to where the buried treasure lies.
(In addition to its name, symbol definition, and variable value, a
symbol has a `drawer' for a "property list" which can be used to record
other information. Property lists are not discussed here; see *Note
Property Lists: (elisp)Property Lists.)
Here is a fanciful representation:
Chest of Drawers Contents of Drawers
---------------------
| |
| symbol name | bouquet
| |
---------------------
| |
| symbol definition | [none]
| |
---------------------
| |
| variable value | (rose violet buttercup)
| |
---------------------
| |
| property list | [not described here]
| |
---------------------
|/ \|
If symbol is set to the CDR of a list, the list itself is not
changed; the symbol simply has an address further down the list. (In
the jargon, CAR and CDR are `non-destructive'.) Thus, evaluation of
the following expression
(setq flowers (cdr bouquet))
produces this:
bouquet flowers
| |
| ___ ___ | ___ ___ ___ ___
--> | | | --> | | | | | |
|___|___|----> |___|___|--> |___|___|--> nil
| | |
| | |
--> rose --> violet --> buttercup
The value of `flowers' is `(violet buttercup)', which is to say, the
symbol `flowers' holds the address of the pair of address-boxes, the
first of which holds the address of `violet', and the second of which
holds the address of `buttercup'.
A pair of address-boxes is called a "cons cell" or "dotted pair".
*Note List Type: (elisp)List Type, and *Note Dotted Pair Notation:
(elisp)Dotted Pair Notation, for more information about cons cells and
dotted pairs.
The function `cons' adds a new pair of addresses to the front of a
series of addresses like that shown above. For example, evaluating the
expression
(setq bouquet (cons 'lilly bouquet))
produces:
bouquet flowers
| |
| ___ ___ ___ ___ | ___ ___ ___ ___
--> | | | | | | --> | | | | | |
|___|___|----> |___|___|----> |___|___|---->|___|___|--> nil
| | | |
| | | |
--> lilly --> rose --> violet --> buttercup
However, this does not change the value of the symbol `flowers', as you
can see by evaluating the following,
(eq (cdr (cdr bouquet)) flowers)
which returns `t' for true.
Until it is reset, `flowers' still has the value `(violet
buttercup)'; that is, it has the address of the cons cell whose first
address is of `violet'. Also, this does not alter any of the
pre-existing cons cells; they are all still there.
Thus, in Lisp, to get the CDR of a list, you just get the address of
the next cons cell in the series; to get the CAR of a list, you get the
address of the first element of the list; to `cons' a new element on a
list, you add a new cons cell to the front of the list. That is all
there is to it! The underlying structure of Lisp is brilliantly simple!
And what does the last address in a series of cons cells refer to?
It is the address of the empty list, of `nil'.
In summary, when a Lisp variable is set to a value, it is provided
with the address of the list to which the variable refers.
* Menu:
* List Exercise::
File: emacs-lisp-intro.info, Node: List Exercise, Prev: List Implementation, Up: List Implementation
Exercise
========
Set `flowers' to `violet' and `buttercup'. Cons two more flowers on
to this list and set this new list to `more-flowers'. Set the CAR of
`flowers' to a fish. What does the `more-flowers' list now contain?
File: emacs-lisp-intro.info, Node: Yanking, Next: Loops & Recursion, Prev: List Implementation, Up: Top
Yanking Text Back
*****************
Whenever you cut text out of a buffer with a `kill' command in GNU
Emacs, you can bring it back with a `yank' command. The text that is
cut out of the buffer is put in the kill ring and the yank commands
insert the appropriate contents of the kill ring back into a buffer
(not necessarily the original buffer).
A simple `C-y' (`yank') command inserts the first item from the kill
ring into the current buffer. If the `C-y' command is followed
immediately by `M-y', the first element is replaced by the second
element. Successive `M-y' commands replace the second element with the
third, fourth, or fifth element, and so on. When the last element in
the kill ring is reached, it is replaced by the first element and the
cycle is repeated. (Thus the kill ring is called a `ring' rather than
just a `list'. However, the actual data structure that holds the text
is a list. *Note Handling the Kill Ring: Kill Ring, for the details of
how the list is handled as a ring.)
* Menu:
* Kill Ring Overview:: The kill ring is a list.
* kill-ring-yank-pointer:: The `kill-ring-yank-pointer' variable.
* yank nthcdr Exercises::
File: emacs-lisp-intro.info, Node: Kill Ring Overview, Next: kill-ring-yank-pointer, Prev: Yanking, Up: Yanking
Kill Ring Overview
==================
The kill ring is a list of textual strings. This is what it looks
like:
("some text" "a different piece of text" "yet more text")
If this were the contents of my kill ring and I pressed `C-y', the
string of characters saying `some text' would be inserted in this
buffer where my cursor is located.
The `yank' command is also used for duplicating text by copying it.
The copied text is not cut from the buffer, but a copy of it is put on
the kill ring and is inserted by yanking it back.
Three functions are used for bringing text back from the kill ring:
`yank', which is usually bound to `C-y'; `yank-pop', which is usually
bound to `M-y'; and `rotate-yank-pointer', which is used by the two
other functions.
These functions refer to the kill ring through a variable called the
`kill-ring-yank-pointer'. Indeed, the insertion code for both the
`yank' and `yank-pop' functions is:
(insert (car kill-ring-yank-pointer))
To begin to understand how `yank' and `yank-pop' work, it is first
necessary to look at the `kill-ring-yank-pointer' variable and the
`rotate-yank-pointer' function.